import 'package:background_downloader/background_downloader.dart';
import 'package:top_foundation/utils/util.dart';
import 'package:whale/helper/component/download/controller.dart';

import 'package:whale/helper/utils/util.dart';

class DownloadState {
  late final dataKeysFileName = 'download-file';
  late List<DownloadFileModel> data = [];
  late List<DownloadModel> list = [];
  late RxList<DownloadModel> valuesChanged = [].cast<DownloadModel>().obs;
}

class DownloadFileModel {
  late final String name;
  late final String path;
  List<DownloadModel>? data;

  double get progress {
    if (data?.isNotEmpty == true) {
      return data!
              .fold(0.0, (previousValue, element) => element.progress.value) /
          data!.length;
    }
    return 0;
  }

  DownloadFileModel({
    required this.name,
    required this.path,
    this.data,
  });
  factory DownloadFileModel.fromJson(Map<String, dynamic> json) =>
      DownloadFileModel(
          name: json['name'],
          path: json['path'],
          data: (json['data'] as List?)
              ?.map((e) => DownloadModel.fromJson(e))
              .toList());

  Map<String, dynamic> toJson() => {
        'name': name,
        'path': path,
        'data': data?.map((e) => e.toJson()).toList(),
      };
}

class DownloadModel {
  late final String httpUri;
  late DownloadTask task;

  late DateTime? date;
  final String dirName;

  int totalSize = 0;

  late RxInt downSize = 0.obs;
  late RxString speed = ''.obs;
  late RxDouble progress = 0.0.obs;

  var status = TaskStatus.notFound.obs;
  var timeRemaining = ''.obs;
  DownloadFileModel get farther {
    return DownloadController()
        .state
        .data
        .firstWhere((element) => element.name == task.directory);
  }

  DownloadModel({
    required this.httpUri,
    required this.task,
    required this.dirName,
    this.date,
  });
  Map<String, dynamic> toJson() => {
        'task': task.toJson(),
        'httpUri': httpUri,
        'progress': progress.value,
        'status': status.value.index,
        'downSize': downSize.value,
        'totalSize': totalSize,
        'dirName': dirName,
      };

  factory DownloadModel.fromJson(Map<String, dynamic> json) => DownloadModel(
      httpUri: json['httpUri'],
      task: DownloadTask.fromJson(json['task']),
      dirName: json['dirName'])
    ..progress.value = json['progress']
    ..status.value = getStatus(json['status'])
    ..downSize.value = json['downSize']
    ..totalSize = json['totalSize']
    ..setStateText();

  void updateStatus(TaskStatusUpdate update) {
    status.value = update.status;
    setStateText();
  }

  void updateProgress(TaskProgressUpdate update) {
    if (update.progress <= progress.value) {
      return;
    }
    progress.value = update.progress;
    timeRemaining.value = update.timeRemainingAsString;
    if (update.progress < 1 && update.expectedFileSize > 1) {
      totalSize = update.expectedFileSize;
      speed.value = update.networkSpeedAsString;
      downSize.value = (totalSize * progress.value).floor();
      if (status.value != TaskStatus.running) {
        updateStatus(TaskStatusUpdate(task, TaskStatus.running));
      }
    }
  }

  var stateText = '下载'.obs;

  setStateText() {
    if (progress.value == 1) {
      stateText.value = Ls.look;
      return;
    }
    switch (status.value) {
      case TaskStatus.notFound:
        stateText.value = Ls.wait;
        break;
      case TaskStatus.enqueued:
        stateText.value = Ls.resume;
        break;
      case TaskStatus.running:
        stateText.value = Ls.pause;
        break;
      case TaskStatus.complete:
        stateText.value = Ls.look;
        break;
      case TaskStatus.failed:
        stateText.value = Ls.retry;
        break;
      case TaskStatus.canceled:
        stateText.value = Ls.download;
        break;
      case TaskStatus.paused:
        stateText.value = Ls.resume;
        break;
      case TaskStatus.waitingToRetry:
        stateText.value = Ls.retry;
        break;
    }
  }

  static TaskStatus getStatus(int index) {
    switch (index) {
      case 0:
        return TaskStatus.enqueued;
      case 1:
        return TaskStatus.running;
      case 2:
        return TaskStatus.complete;
      case 3:
        return TaskStatus.notFound;
      case 4:
        return TaskStatus.failed;
      case 5:
        return TaskStatus.canceled;
      case 6:
        return TaskStatus.waitingToRetry;
      case 7:
        return TaskStatus.paused;
      default:
        return TaskStatus.notFound;
    }
  }
}
